package com.wondream.myframework.app.request.profitsharing;

import cn.hutool.core.io.file.FileWriter;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import org.junit.Test;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

/**
 * 获取证书, 私钥方法
 * @author ZhangYi
 * @date 2021/05/13 17:43
 */
public class PemUtil {

    /**
     * 获取私钥
     * @param privateKey 私钥的内容
     */
    public static PrivateKey loadPrivateKeyFromString(String privateKey) {
        InputStream inputStream = null;
        ByteArrayOutputStream array = null;
        try {
            inputStream = new ByteArrayInputStream(privateKey.getBytes("utf-8"));
            array = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                array.write(buffer, 0, length);
            }

            String privateKeyNew = array.toString("utf-8")
                    .replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyNew)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        } catch (IOException e) {
            throw new RuntimeException("无效的密钥");
        } finally {
            if(inputStream!=null){
                try{
                    inputStream.close();
                } catch (Exception e){}
            }
            if(array!=null){
                try{
                    array.close();
                } catch (Exception e){}
            }
        }
    }

    /**
     * 获取私钥
     * @param filename 私钥存放地址路径
     */
    public static PrivateKey loadPrivateKey(String filename) {
        try {
            InputStream inputStream = new FileInputStream(filename);
            ByteArrayOutputStream array = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                array.write(buffer, 0, length);
            }

            String privateKey = array.toString("utf-8")
                    .replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        } catch (IOException e) {
            throw new RuntimeException("无效的密钥");
        }
    }


    /**
     * 获取证书
     */
    public static X509Certificate loadCertificate(String filename) {
        X509Certificate cert;
        try {
            InputStream fis = new FileInputStream(filename);
            BufferedInputStream bis = new BufferedInputStream(fis);
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            cert = (X509Certificate) cf.generateCertificate(bis);
            cert.checkValidity();
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateException e) {
            throw new RuntimeException("无效的证书", e);
        } catch (FileNotFoundException e) {
            throw new RuntimeException("获取证书失败", e);
        }
        return cert;
    }


    /**
     * 获取证书序列号
     * @param filename 证书存放地址路径
     */
    public static String getCertificateSerialNumber(String filename) {
        X509Certificate certificate = PemUtil.loadCertificate(filename);
        return certificate.getSerialNumber().toString();
    }

    /**
     * 获取证书
     *
     * @param inputStream 证书文件
     * @return {@link X509Certificate} 获取证书
     */
    public static X509Certificate getCertificate(InputStream inputStream) {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
            cert.checkValidity();
            return cert;
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }

    public static String savePlatformCert(String associatedData, String nonce, String cipherText, String certPath) {
        try {
            String apiKey3 = "KYz2eZK2DzdXOJiKnkaxBxoZQJba2OgK";
            AesUtil aesUtil = new AesUtil(apiKey3.getBytes(StandardCharsets.UTF_8));
            // 平台证书密文解密
            // encrypt_certificate 中的  associated_data nonce  ciphertext
            String publicKey = aesUtil.decryptToString(
                    associatedData.getBytes(StandardCharsets.UTF_8),
                    nonce.getBytes(StandardCharsets.UTF_8),
                    cipherText
            );
            // 保存证书
            cn.hutool.core.io.file.FileWriter writer = new FileWriter(certPath);
            writer.write(publicKey);
            // 获取平台证书序列号
            X509Certificate certificate = PemUtil.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));
            return certificate.getSerialNumber().toString(16).toUpperCase();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Test
    public void test(){
//        String certPathV3 = "Z:\\apiclient_cert.pem";
//        String serialNo = PemUtil.getCertificateSerialNumber(certPathV3);
//        System.out.println(serialNo);

        String platformCertPathV3 = "Z:\\platform_cert.pem";
        String algorithm = "AEAD_AES_256_GCM";
        String associated_data = "certificate";
        String nonce = "42402848e560";
        String ciphertext = "t7ted9TgIKWruwR79qzmT5c1S0/nJSjwRBx/zDCBr+09pyVF292Vd3ETlzi52mttWYWb4n26WhB/+13q2SpUDxxcj/hmLpvDCjPTrNJldNh9BI54l06UrzEugvLflmUA6lDmdvyqhMQZKggF5RV/BWeWXv4gPCxUmSRqNUwk75/wr4jBIhj2c1dgoMriC9i4U4+AnvI/wnp1/TcIsU2URXwEZO6QBglNDA6F6szmer6P/xNEkxBlNgvC/L3aYi+x0WbvUa5rnPN6lg8ngvMPrfLuaOd3IhZW88HOWD2hH2TQq/ruDiig0MlnqTjRef1lfkM8BwmKOYLlN7HDUhodCkBNxV3tkjdUx65ij7eIz/1X8woA7fu/WeqkovsZypxLAm3JkdXbS/vkR1KCzEzq5yeHSNLUrX1571IIlcStqsL0FBpDNDGBB0aeKz+jOyPszQMv1LgUZi15o0yR/egYIh8GMcs8KpjItdLVxNphCauji3Fu992nDeDd8lWeN2ExB+bKcyT+qBA+uhQldTAUwZ8OnQqhMLCafsv/R7PiIJ0wlnpYNUxeGnqoJyr8ZI0t28kyFF0fIhV7g3dtH+hpqte5/mdHyg5mwRVjaHG60eTramWyLCd2e1FA1js1gF5Evp4kxe2EITHf85DTsXhRe65Sw7HcTHZGNxI84lZTy+Of8laipZjis++SiLNbqQtrY/Zf3Gf8s8le2Z/vHlAEegTxQ1Yn6klyeT1/CJdZ0iQrb5pT7nYUGqYlj7t4zjON9NJJuOLXG3W13IT3t6lUNKLiaUPTUaiASTotaxLmJ41unyKMCLh0L5P06WJQHbBWYIyGXpTMSjh6eeh7ChZzH8XLBC/FBEThs1LM2yWxowXt5K8eoE35LkE+nB2yrU3S6vILVcPk1R/0jIsZ68GhNUDJ6iYVUosho2241+lC/ebRinai1lXzCAO/nQ4RhzlFnf6RpdNh0kCBWRQW/TjWFG4yHTYrVk+7SF3aC6J5cF+inxpkulKLlNB6GBD2u7IsD1KvjwhT/+FfI1O6ShtI0dsxDBZBoEuPq2f2afoJv3GrZTxILn11Hf7Dyobf63nXMEmPsyxL8k1Sd4sJDxl4Zlchf1nlzjAAxCYmqPPJlmqjFkfbXJVCwN+Ro4W6wDeCoGghLpJ1wDCJNfPwV+nCp26BpONQDbJgivzTAQDdrswXVI1uWPB2p65gTmQ6O+Kd405k7gA1gZNtW+Lon8QAzxyNQTJA6iHDCvsOUDVcqb6XJN0cZrEKCUQIkxPs56R0N73V/XMpDYKgsA5qUOGaAHAUUPSZ0JgZ5cdRLl8FTfEqcYXeN61bvl06652FCTLtx7LXFTBgT5VerIpTQ/88dKVg+y3KPOCAPCbEpcCsd729lR+lHX2X3O36Y3l9XTVPwzLu5uDSfcMRwXDzt4dHT1Hnb24UkofJMyB9WgB6MrERS9LYi5GkPRwIKg4MlHJzPpItrCIA6effw1Z4E3YDm+3XLcYm9H/3mCgLVUVAvu8ZhC8rPSZlg0skB4F5rtExxlrbvWktKSG116VdTIL7g3bOXkRMZDMgBRGhIeNFSFa3hCCA8yfqHbarChhWtVFLy8iLyXZfZa7WZ10y1/FwHXVmXQq2dFdTP/usLkgn/9FK1C6hYeXldWJge9dGNA6uXb8H4iVFwFXAFD+odd1OqL7LyNiFQLRNTeFsLpHPAil6pMzyg5fDRj5vP1sz4+0EMabMq7RwfqofvOdAPHWaYyBM71tWrV8V+I6HYmWIh1ddH2OUmq7Zp+xTOktOlP/f/gUhbY0KpsIygsbMkoUgF553lyglzBRWRAdMX8F5qxh+FG+KIXR+93VqYW8/w1xKLIyPfDIVYv5pOCE30XYELS4D7b2vmw==";
        PemUtil.savePlatformCert(associated_data, nonce, ciphertext, platformCertPathV3);

    }

}
